#!/usr/local/bin/perl -w
use strict;

use EV;
use IO::Socket::INET;
use Time::HiRes qw(gettimeofday);

my $addr = "127.0.0.1";
my $port = 8010;
my $max = 30_000;
my $counters = {
	array => [],
	clients => 0,
	closed => 0,
	refused => 0,
};
my $fh;
run();

sub loger {
	my ($tm) = @_;
	printf $fh "%f %d %d %d\n",$tm,@{$counters}{qw(clients closed refused)};
}
sub run{
	open $fh,">log.txt";
	my $sg;
	if(client()){
		$sg = EV::signal( 'INT', sub {
			print "\nSIGINT, will now quit\n";
			EV::break EV::BREAK_ALL;
		});
		EV::loop;
	}else{
		print "cannot connect $@\n";
	}
	close $fh;
}
sub client {
	my $s = IO::Socket::INET->new(
		PeerAddr => $addr,
		PeerPort => $port,
	);
	unless($s){
		$counters->{refused}++;
		return 0;
	}
	
	my $w = EV::io $s, EV::WRITE, \&can_write;
	$w->data([scalar(@{$counters->{array}}),"Hello, world!"]);
	push @{$counters->{array}},$w;
	$counters->{clients} = scalar(@{$counters->{array}});
	print $counters->{clients},"\n";
	return $counters->{clients};
}
sub can_write {
	my ($w) = @_;
	my $need = length($w->data->[1]);
	my $r = $w->fh->send($w->data->[1]);
	if($r){
		if($r < $need){
			substr($w->data->[1],0,$r,"");
		}else{
			my $nw = EV::io $w->fh,EV::READ,\&can_read;
			my $data = $w->data;
			$w->data("");
			$data->[1] = "";
			$counters->{array}[$data->[0]] = $nw;
			$data->[2] = gettimeofday();
			$nw->data($data);
#			print "sended $r\n";
		}
	}else{
		$counters->{close}++;
		$counters->{array}[$w->data->[0]] = undef;
		print "closed\n";
	}
}
sub can_read {
	my ($w) = @_;
	my $buf;
	$w->fh->recv($buf,1024);
	unless($buf){
		$counters->{close}++;
		$counters->{array}[$w->data->[0]] = undef;
	}else{
		$w->data->[1] .= $buf;
		while($w->data->[1] =~ s/(.*)\n//){
			my $line = $1;
		}
		if($w->data->[2]){
			my $tm = gettimeofday() - $w->data->[2];
			$w->data->[2] = 0;
			loger($tm);
			if($counters->{clients} < $max){
				unless(client()){
					print STDERR "error: $@\n";
					EV::break EV::BREAK_ALL;
				}
			}else{
				print STDERR "all done\n";
				EV::break EV::BREAK_ALL;
			}
		}
	}
}
